﻿// --------------------------------
// <copyright file="AMenuItemList.cs" company="Faculty of Information Technology, Czech Technical University in Prague">
//     This document is shared by Microsoft Public License (MS-PL)
//     For further details please see http://msdn.microsoft.com/en-us/library/ff648068.aspx or license.txt.
// </copyright>
// <author>Lukáš Molnár</author>

// <email>molnaluk@fit.cvut.cz</email>

// <date>7. 12. 2011 18:54:01</date>

// <summary>
//
// </summary>
// --------------------------------
#if WINDOWS

using Nuclex.Input;
using ExternalClasses.Controls;
using System.ComponentModel;
using FITClub.Episode1.Levels;
using System.Drawing.Design;

#endif

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;
using System.Xml.Serialization;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using FITClub.Util;

namespace FITClub.TextureMenu
{
#if WINDOWS

    [System.Serializable]
#endif
    /// <summary>
    /// Base class for list menu item.
    /// </summary>
    /// <typeparam name="T">List value type</typeparam>
    [XmlInclude(typeof(SoundItem))]
    public abstract class AMenuItemList<T> : AMenuItem, IUpdateableItem
    {
        #region Public properties

        /// <summary>
        ///
        /// </summary>
        [XmlArray]
        [XmlArrayItem(ElementName = "Item")]
#if WINDOWS
        [Category("Content")]
#endif
        public List<T> Options { get; set; }

        /// <summary>
        ///
        /// </summary>
        [XmlAttribute]
#if WINDOWS
        [Category("Content")]
#endif
        public int SelectedIndex { get; set; }

        /// <summary>
        /// Colof of text on textual lists
        /// </summary>
#if WINDOWS

        [Category("Colors")]
        [Editor(typeof(ContentPathEditor), typeof(UITypeEditor))]
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        [XmlElement]
        public Color TextColor { get; set; }

        /// <summary>
        ///
        /// </summary>
        [XmlElement]
#if WINDOWS
        [Category("Colors")]
        [Editor(typeof(ContentPathEditor), typeof(UITypeEditor))]
        [EditorBrowsable(EditorBrowsableState.Always)]
#endif
        public Color SelectionColor { get; set; }

        /// <summary>
        /// Sound played afrer item traversal.
        /// </summary>
#if WINDOWS

        [TypeConverter(typeof(ExpandableObjectConverter))]
        [Category("Behaviour")]
#endif
        [XmlElement]
        public SoundItem SelectionSound { get; set; }

        /// <summary>
        /// True to avoid the setting of action parameter on selection change.
        /// </summary>
#if WINDOWS

        [Category("Behaviour")]
#endif
        [XmlAttribute]
        public bool IgnoreParam { get; set; }

        #endregion Public properties

        protected Point offset = new Point(5, 5);
        protected Rectangle prevItemBounds;
        protected Rectangle nextItemBounds;
        protected int allowHDrag = 0;

        public AMenuItemList()
        {
            PlayPushedSound = false;
        }

        /// <summary>
        /// Select next option/value.
        /// </summary>
        public virtual void NextItem()
        {
            TraverseItems(1);
        }

        /// <summary>
        /// Select previous option/value.
        /// </summary>
        public virtual void PreviousItem()
        {
            TraverseItems(-1);
        }

        /// <summary>
        /// Select next X neighbour according to parameter.
        /// </summary>
        /// <param name="selectionMove"></param>
        public virtual void TraverseItems(int selectionMove)
        {
            if (this.Options == null || this.Options.Count == 0) return;
            this.SelectedIndex = (this.SelectedIndex + selectionMove) % this.Options.Count;
            if (this.SelectedIndex < 0)
            {
                this.SelectedIndex += this.Options.Count;
            }
            if (this.SelectionSound != null)
            {
                this.SelectionSound.Play();
            }
            if (this.Action != null && this.IgnoreParam == false && this.Options.Count > 0)
            {
                this.Action.Param = this.Options[this.SelectedIndex].ToString();
            }
        }

        /// <summary>
        /// Update input.
        /// </summary>
        /// <param name="gt"></param>
        public virtual void Update(GameTime gt)
        {
            if (this.IsEnabled == false) return;
#if WINDOWS_PHONE
            if (MenuManager.Current.TapTest(nextItemBounds))
            {
                this.NextItem();
                return;
            }
            if (MenuManager.Current.TapTest(prevItemBounds))
            {
                this.PreviousItem();
                return;
            }

#endif
            if (MenuManager.Current.HitTest(Keys.Left, MenuManager.Current.cycles) || MenuManager.Current.MouseUpTest(prevItemBounds))
            {
                this.PreviousItem();
                return;
            }
            if (MenuManager.Current.HitTest(Keys.Right, MenuManager.Current.cycles) || MenuManager.Current.MouseUpTest(nextItemBounds))
            {
                this.NextItem();
                return;
            }
        }

        public override void Move(Point delta)
        {
            base.Move(delta);
            this.nextItemBounds = this.nextItemBounds.OffsetXY(delta.X, delta.Y);
            this.prevItemBounds = this.prevItemBounds.OffsetXY(delta.X, delta.Y);
        }
    }
}